package raytracer;

public class Toolbox
{
	// vector normalization
    // CAUTION: vec is an in-/output parameter; the referenced object will be altered!
    public static float normalize(float[] vec) 
    {
    	float l = (float) Math.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);

    	vec[0] = vec[0] / l;
    	vec[1] = vec[1] / l;
    	vec[2] = vec[2] / l;
    	
    	return l;
    }
    
    // calculate normalized face normal fn of the triangle p1, p2 and p3
    // the return value is the area of triangle
    // CAUTION: fn is an output parameter; the referenced object will be
    // altered!
    public static float calculateN(float[] fn, float[] p1, float[] p2, float[] p3) 
    {
		float ax, ay, az, bx, by, bz;
	
		// a = Vi2-Vi1, b = Vi3-Vi1
		ax = p2[0] - p1[0];
		ay = p2[1] - p1[1];
		az = p2[2] - p1[2];
		
		bx = p3[0] - p1[0];
		by = p3[1] - p1[1];
		bz = p3[2] - p1[2];
		
		// n = a x b
		fn[0] = ay * bz - az * by;
		fn[1] = az * bx - ax * bz;
		fn[2] = ax * by - ay * bx; 
	
		// normalize n, calculate and return area of triangle
		return normalize(fn) / 2;
    }
    
    // calculate triangle test
    // is p (the intersection point with the plane through p1, p2 and p3) inside
    // the triangle p1, p2 and p3?
    // the return value answers this question
    // a is an input parameter - the given area of the triangle p1, p2 and p3
    // ai will be computed to be the areas of the sub-triangles to allow to
    // compute barycentric coordinates of the intersection point p
    // ai[0] is associated with bu (p1p2p) across from p3
    // ai[1] is associated with bv (pp2p3) across from p1
    // ai[2] is associated with bw (p1pp3) across form p2
    // CAUTION: barycentric is an output parameter; the referenced object will be
    // altered!
    public static boolean triangleTest(float[] p, float[] p1, float[] p2, float[] p3, float a, float barycentric[]) 
    {
		float tmp[] = new float[3];
	
		barycentric[0] = calculateN(tmp, p1, p2, p) / a;
		barycentric[1] = calculateN(tmp, p, p2, p3) / a;
		barycentric[2] = calculateN(tmp, p1, p, p3) / a;
	
    	float sum = barycentric[0] + barycentric[1] + barycentric[2];
    	
    	// more precise than sum of triangles
		if ( Math.abs(sum - 1.0f) <  1E-5)
		    return true;
	
		return false;
    }
}
